﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace GraphicsEditor.Other
{
    class Histogram
    {
        public List<int> allValues;
        public List<int> redValues;
        public List<int> blueValues;
        public List<int> greenValues;

        public Bitmap image;
        public Bitmap redImage;
        public Bitmap blueImage;
        public Bitmap greenImage;

        public Histogram( Bitmap toGetHistogram)
        {
            allValues = new List<int>();
            redValues = new List<int>();
            blueValues = new List<int>();
            greenValues = new List<int>();

            GetHistogram(toGetHistogram);

            image = new Bitmap(800, 600, PixelFormat.Format24bppRgb);
            image = Filters.makeBlank(image);
            redImage = new Bitmap(image);
            blueImage = new Bitmap(image);
            greenImage = new Bitmap(image);
            Rectangle bounds = new Rectangle(0, 0, image.Width, image.Height);

            drawHistogram(Graphics.FromImage(image), bounds, Color.Black, allValues);
            drawHistogram(Graphics.FromImage(redImage), bounds, Color.Red, allValues);
            drawHistogram(Graphics.FromImage(blueImage), bounds, Color.Blue, allValues);
            drawHistogram(Graphics.FromImage(greenImage), bounds, Color.Green, allValues);
        }

        private void GetHistogram(System.Drawing.Bitmap picture)
        {
            BitmapData bmData = picture.LockBits(new Rectangle(0, 0, picture.Width, picture.Height),
            ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            int stride = bmData.Stride;
            IntPtr Scan0 = bmData.Scan0;
            // haha, even C# considers pointers unsafe!
            // The only way to access the pixel data is through pointers
            unsafe
            {
                byte* pixel = (byte*)(void*)Scan0;

                int nOffset = stride - picture.Width * 4;

                byte alpha, red, green, blue;

                for (int y = 0; y < picture.Height; ++y)
                {
                    for (int x = 0; x < picture.Width; ++x)
                    {
                        blue = pixel[0];
                        green = pixel[1];
                        red = pixel[2];
                        alpha = pixel[3];
                        redValues.Add(red);
                        blueValues.Add(blue);
                        greenValues.Add(green);
                        int temp = 0;
                        temp += blue;
                        temp += red;
                        temp += green;
                        temp = temp / 3;
                        allValues.Add(temp);
                        pixel += 4;
                    }
                    pixel += nOffset;
                }
            }
            picture.UnlockBits(bmData);
        }

        public void drawHistogram(Graphics g, Rectangle bounds, Color color, List<int> values)
        {
            int maxValue = values.Max();
            float yUnit = (float)bounds.Height / maxValue;
            float xUnit = (float)bounds.Width / values.Count;

            Pen myPen = new Pen(new SolidBrush(color), xUnit);
            int skips = (values.Count / bounds.Width)/4; // good idea of what it looks like while maintaining performance
            Console.WriteLine(values.Count + " <-count width-> " + bounds.Width + " Skips = " + skips);
            //The width of the pen is given by the XUnit for the control.
            for (int i = 0; i < values.Count; i+= skips)
            {
                PointF lineStart = new PointF(i * xUnit, bounds.Height);
                PointF lineEnd = new PointF(i * xUnit, bounds.Height - values[i] * yUnit);
               
                //We draw each line
                g.DrawLine(myPen, lineStart, lineEnd);
            }
        }
    }
}
